package projectx.util;

import game.web.dao.dto.UserDTO;
import game.web.viewhelper.WithdrawInitViewHelper;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

public class ClassUtil {

	public static void main(String args[])
	{
		WithdrawInitViewHelper viewHelper = new WithdrawInitViewHelper();
		UserDTO userDTO = new UserDTO();
		userDTO.setMoney(0.89);
		ClassUtil.copyData(userDTO, viewHelper);
		System.err.println(userDTO.getMoney());
		System.err.println(viewHelper.getMoney());

		System.err.println(userDTO.getLevel());
		System.err.println(viewHelper.getLevel());
		
	}
	public static String getClassName(Object obj) {
		String fullName = obj.getClass().getName();
		StringTokenizer token = new StringTokenizer(fullName, ".");
		String className = fullName;
		while (token.hasMoreTokens()) {
			className = token.nextToken();
		}
		return className;

	}

	public static void copyData(Object ObjectSrc, Object ObjectDes) {
		if(ObjectSrc==null||ObjectDes==null)
			return;
		Class clsSrc = ObjectSrc.getClass();
		Class clsDes = ObjectDes.getClass();
		try {
			clsSrc.newInstance();
			clsDes.newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		Field fSrc[] = clsSrc.getDeclaredFields();
		Field superfSrc[] =clsDes.getSuperclass().getDeclaredFields();
		
		List<Field> fSrcL = Arrays.asList(fSrc);
		List<Field> superfSrcL = Arrays.asList(superfSrc);
		List<Field> fSrcList = new ArrayList<Field>();   
		fSrcList.addAll(fSrcL);
		fSrcList.addAll(superfSrcL);
		fSrc = fSrcList.toArray(new Field[fSrcList.size()]);
		
		Map fSrcMap = getMethodToMap(clsSrc);
		
		
		Field fDes[] = clsDes.getDeclaredFields();
		Field superfDes[] =clsDes.getSuperclass().getDeclaredFields();
		
		List<Field> fDesL = Arrays.asList(fDes);
		List<Field> superfDesL = Arrays.asList(superfDes);
		List<Field> fDesList = new ArrayList<Field>();   
		fDesList.addAll(fDesL);
		fDesList.addAll(superfDesL);
		
		fDes = fDesList.toArray(new Field[fDesList.size()]);
		
		Map fDesMap = getMethodToMap(clsDes);

		for (Field fieldSrc : fSrc) {
			for (Field fieldDes : fDes) {
				if (fieldSrc.getName().equals(fieldDes.getName())
						&& fieldSrc.getType().equals(fieldDes.getType())
						&& fieldSrc.getModifiers() == fieldDes.getModifiers()) {
					String getFun = "get"
							+ fieldSrc.getName().toString().substring(0, 1)
									.toUpperCase()
							+ fieldSrc.getName().toString().substring(1);
					String setFun = "set"
							+ fieldSrc.getName().toString().substring(0, 1)
									.toUpperCase()
							+ fieldSrc.getName().toString().substring(1);

					if (!fSrcMap.containsKey(getFun)) {
						continue;
					}
					Method MethodSrc = null;
					try {
						MethodSrc = clsSrc.getMethod(getFun, new Class[] {});
					} catch (SecurityException e) {
						e.printStackTrace();
					} catch (NoSuchMethodException e) {
						e.printStackTrace();
					}
					Object ResultSrc = null;
					try {
						ResultSrc = MethodSrc
								.invoke(ObjectSrc, new Object[] {});
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					} catch (InvocationTargetException e) {
						e.printStackTrace();
					}

					if (!fDesMap.containsKey(setFun)) {
						continue;
					}
					Method MethodDes = null;
					try {
						MethodDes = clsDes.getMethod(setFun,
								new Class[] { fieldSrc.getType() });
					} catch (SecurityException e) {
						e.printStackTrace();
					} catch (NoSuchMethodException e) {
						e.printStackTrace();
					}
					try {
						MethodDes.invoke(ObjectDes, new Object[] { ResultSrc });
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					} catch (InvocationTargetException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
	

	@SuppressWarnings("unchecked")
	public static Map getMethodToMap(Object Obj) {
		Map map = new HashMap();
		for (int i = 0; i < ((Class<?>) Obj).getMethods().length; i++) {
			Method method = ((Class<?>) Obj).getMethods()[i];
			map.put(method.getName(), method);
		}
		return map;
	}


}
